#include "StdAfx.h"
#include "EchoServerAO.h"
#include "DynamicBindPayload.h"

namespace CO { namespace SpiFoundation { namespace RoomFW {

using namespace SpiControl::Protocol;

EchoServerAO::EchoServerAO(const char* objectName) :
	//
	// Initialize Base class.
	//
	SpiFoundation::RoomFW::ActiveObject(PORT_COUNT,
		SpiFoundation::RoomFW::ActiveObject::PortPriorityArray(&PortPriorities[0], &PortPriorities[PortPrioritiesSize])),
	//
	// TODO:  Initialize attributes.
	//
	objectName_(objectName)
{
	G_LOG_1_TRACE("EchoServerAO::EchoServerAO(%s)", objectName);
}

EchoServerAO::~EchoServerAO(void)
{
}

const char* EchoServerAO::getObjectName(void) const
{
	return objectName_.c_str();
}

void EchoServerAO::handle(SpiFoundation::RoomFW::RoomMessageSP message)
{
	switch (message->portIndex().port())
	{
	case PORT_ECHO_IN:
		{
			switch (message->messageID())
			{
			case GenericTestProtocol::IN_STRING_MESSAGE1:
				{
					StringPayloadSP payload =
						::boost::dynamic_pointer_cast<StringPayload>(message->payload());
					ASSERT(0 != payload);
					message->reply(GenericTestProtocol::OUT_STRING_MESSAGE1, PAYLOAD1(StringPayload, payload->value()));
					this->sendMessage(PORT_ECHO_IN, GenericTestProtocol::OUT_STRING_MESSAGE1, PAYLOAD1(StringPayload, payload->value()));
					if (this->isBound(PORT_ECHO_OUT))
					{
						this->sendMessage(PORT_ECHO_OUT, GenericTestProtocol::IN_STRING_MESSAGE1, PAYLOAD1(StringPayload, payload->value()));
					}
				}
				break;
			case GenericTestProtocol::IN_DYNAMIC_BIND:
				{
					DynamicBindPayloadSP payload = ::boost::dynamic_pointer_cast<DynamicBindPayload>(message->releasePayload());
					ASSERT(0 != payload);
					for (size_t i = 0; i < 10; ++i)
					{
						BindingSP binding = this->dynamicBind(payload->first(), payload->second().c_str());
						if (binding)
						{
							bindings_.push_back(binding);
							break;
						}
						else
						{
							::Sleep(250);
						}
					}
				}
				break;
			}
		}
		break;
	case PORT_ECHO_OUT:
		{
			switch (message->messageID())
			{
			case GenericTestProtocol::OUT_STRING_MESSAGE1:
				{
					StringPayloadSP payload =
						::boost::dynamic_pointer_cast<StringPayload>(message->payload());
					ASSERT(0 != payload);
					if (this->isBound(PORT_ECHO_IN))
					{
						this->sendMessage(PORT_ECHO_IN, GenericTestProtocol::OUT_STRING_MESSAGE1, PAYLOAD1(StringPayload, payload->value()));
					}
				}
				break;
			}
		}
		break;
	case PORT_TIMER: // Handle timer messages.
		{
			SpiFoundation::RoomFW::RoomTimer::TimerId timerId = message->messageID();
			ASSERT(SpiFoundation::RoomFW::RoomTimer::InvalidTimerId != timerId);
			//
			// TODO:  Handle timer id.
			//
			// Test error handling.
			throw std::runtime_error("Timer Error");
		}
		break;
	default:
		ASSERT(FALSE); // No more ports!
		throw std::runtime_error("Unexpected Message Error");
	}
}

void EchoServerAO::onStart()
{
	G_TRACE_METHOD(EchoServerAO::onStart);

	this->registerRemoteDynamicPort(PORT_ECHO_IN);
	this->registerRemoteDynamicPort(PORT_ECHO_OUT);
}

void EchoServerAO::onError(SpiFoundation::ErrorHandling::IError& e)
{
	//
	// TODO: Remove logging and Handle the error.  DEFAULT_HSM_CATCH_BLOCKS already logs.
	//
	G_LOG_1_ERROR("EchoServerAO::onError(%s)", e.what());
}

void EchoServerAO::onException(std::exception& e)
{
	//
	// TODO: Remove logging and Handle the error.  DEFAULT_HSM_CATCH_BLOCKS already logs.
	//
	G_LOG_1_ERROR("EchoServerAO::onException(%s)", e.what());
}

void EchoServerAO::onCatchAllException()
{
	//
	// TODO: Remove logging and Handle the error.  DEFAULT_HSM_CATCH_BLOCKS already logs.
	//
	G_LOG_0_ERROR("EchoServerAO::onCatchAllException()");
}

}}}